/**
 * @author BelovedLYC
 * @fileoverview 音频消息组件，用于显示和播放语音消息
 *
 * @component VoiceMessage
 * @description 显示音频消息气泡并提供音频播放功能，支持显示时长和音波动画。
 * 左侧显示时长（格式为"15s"），右侧显示波形，点击可播放/暂停。
 * 还支持消息状态指示：发送中、发送失败、发送成功。
 *
 * @example
 * ```tsx
 * <VoiceMessage
 *   audioSource={{
 *     fileUrl: "https://example.com/audio.m4a",
 *     fileName: "voice_12345.m4a",
 *     fileInfo: {
 *       duration: 15,
 *       bitRate: 128000,
 *       sampleRate: 44100,
 *       audioChannel: 2
 *     }
 *   }}
 *   messageId="12345"
 *   isCurrentUser={true}
 *   setShow={setShowMenu}
 *   status={ChatMessageStatus.SUCCESS}
 *   onRetry={() => resendMessage("12345")}
 * />
 * ```
 *
 * @typedef {Object} AudioType
 * @property {number} duration - 音频时长（秒）
 * @property {number} bitRate - 比特率
 * @property {number} sampleRate - 采样率
 * @property {number} audioChannel - 音频通道数
 */

import React, { useState, useEffect } from "react";
import {
  View,
  Text,
  TouchableOpacity,
  Animated,
  ActivityIndicator,
} from "react-native";
import { MaterialIcons } from "@expo/vector-icons";
import { Audio } from "expo-av";
import styles from "./index.style";
import { UploadFileResult } from "@/types/file-upload";
import { MessageStatus } from "@/types/chat-message";

interface AudioType {
  duration: number;
  bitRate: number;
  sampleRate: number;
  audioChannel: number;
}

/**
 * @interface VoiceMessageProps
 * @property {UploadFileResult<AudioType>} audioSource - 音频文件信息和元数据
 * @property {string} messageId - 消息ID
 * @property {boolean} isCurrentUser - 是否为当前用户发送的消息
 * @property {boolean} [isPlayed=true] - 消息是否已被播放过
 * @property {function} setShow - 控制菜单显示的函数
 * @property {MessageStatus} [status=MessageStatus.SUCCESS] - 消息状态
 * @property {function} [onRetry] - 重试发送回调函数
 */
interface VoiceMessageProps {
  audioSource: UploadFileResult<AudioType>;
  isCurrentUser: boolean;
  isPlayed?: boolean;
  setShow: (value: boolean) => void;
}

/**
 * 音频消息组件
 *
 * @remarks
 * 根据消息状态显示不同的UI：
 * - 发送中：显示加载指示器
 * - 发送失败：显示错误图标，点击可重试
 * - 成功：显示时长和波形，点击播放/暂停
 *
 * 波形动画在播放时活跃，暂停时静止
 */
const VoiceMessage: React.FC<VoiceMessageProps> = ({
  audioSource,
  isCurrentUser,
  isPlayed = true,
  setShow,
}) => {
  const [sound, setSound] = useState<Audio.Sound | null>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [playbackPosition, setPlaybackPosition] = useState(0);
  const [duration, setDuration] = useState(audioSource.fileInfo.duration || 0);

  // 为波形创建动画值
  const waveLines = Array(12)
    .fill(0)
    .map(
      (_, i) =>
        React.useRef(
          new Animated.Value(i % 3 === 0 ? 15 : i % 2 === 0 ? 10 : 5)
        ).current
    );

  /**
   * 格式化时间为 Xs 格式，如 "15s"
   * @param {number} seconds - 秒数
   * @returns {string} 格式化后的时间字符串
   */
  const formatTime = (seconds: number) => {
    const secs = Math.floor(seconds);
    return `${secs}s`;
  };

  /**
   * 播放音频
   * 加载中或失败状态下不允许播放
   */
  const togglePlayback = async () => {
    try {
      if (sound) {
        if (isPlaying) {
          await sound.pauseAsync();
          setIsPlaying(false);
        } else {
          await sound.playAsync();
          setIsPlaying(true);
        }
      } else {
        await loadSound();
      }
    } catch (error) {
      console.error("Error toggling playback:", error);
    }
  };

  /**
   * 加载音频文件
   */
  const loadSound = async () => {
    try {
      const { sound: newSound } = await Audio.Sound.createAsync(
        { uri: audioSource.fileUrl },
        { shouldPlay: true },
        onPlaybackStatusUpdate
      );
      setSound(newSound);
      setIsPlaying(true);
    } catch (error) {
      console.error("Error loading sound:", error);
    }
  };

  /**
   * 播放状态更新回调
   * 更新当前播放位置并处理播放结束事件
   */
  const onPlaybackStatusUpdate = (status) => {
    if (status.isLoaded) {
      setPlaybackPosition(status.positionMillis / 1000);

      if (status.didJustFinish) {
        setIsPlaying(false);
        setPlaybackPosition(0);
      }
    }
  };

  /**
   * 音波动画效果
   * 播放时波形动态变化，暂停时恢复静态波形
   */
  useEffect(() => {
    if (isPlaying) {
      const animations = waveLines.map((line, index) => {
        const randomHeight = 5 + Math.random() * 15;
        return Animated.timing(line, {
          toValue: randomHeight,
          duration: 300 + index * 50,
          useNativeDriver: false,
        });
      });

      const animateWaves = () => {
        Animated.parallel(animations).start(() => {
          if (isPlaying) {
            animateWaves();
          }
        });
      };

      animateWaves();
    } else {
      // 重置波形
      waveLines.forEach((line, index) => {
        Animated.timing(line, {
          toValue: index % 3 === 0 ? 15 : index % 2 === 0 ? 10 : 5,
          duration: 300,
          useNativeDriver: false,
        }).start();
      });
    }
  }, [isPlaying]);

  /**
   * 组件卸载时清理资源
   */
  useEffect(() => {
    return () => {
      if (sound) {
        sound.unloadAsync();
      }
    };
  }, [sound]);

  return (
    <TouchableOpacity
      style={[
        styles.container,
        {
          backgroundColor: isCurrentUser ? "#d0e6ff" : "#e0e0e0",
          borderBottomRightRadius: isCurrentUser ? 0 : 8,
          borderBottomLeftRadius: isCurrentUser ? 8 : 0,
        },
      ]}
      onPress={togglePlayback}
      onLongPress={() => setShow(true)} // 只有非加载状态才允许长按
    >
      <View style={styles.infoContainer}>
        {/* 左侧：状态或时长 */}
        <Text
          style={[
            styles.durationText,
            { color: isCurrentUser ? "#3390ec" : "#555" },
          ]}
        >
          {formatTime(isPlaying ? playbackPosition : duration)}
        </Text>

        {/* 右侧：波形 */}
        <View style={styles.waveContainer}>
          {waveLines.map((line, index) => (
            <Animated.View
              key={index}
              style={[
                styles.waveLine,
                {
                  height: line,
                  backgroundColor: isCurrentUser ? "#3390ec" : "#666",
                },
              ]}
            />
          ))}

          {!isPlayed && <View style={styles.notPlayedIndicator} />}
        </View>
      </View>
    </TouchableOpacity>
  );
};

export default VoiceMessage;
